package com.baijiayun.live.ui.pptpanel

import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build
import android.provider.Settings
import android.util.Log
import android.view.*
import android.view.GestureDetector.SimpleOnGestureListener
import android.widget.FrameLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.content.ContextCompat
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.Observer
import com.baijia.bjydialog.DialogAction
import com.baijia.bjydialog.MaterialDialog
import com.baijiayun.live.ui.*
import com.baijiayun.live.ui.activity.LiveRoomBaseActivity
import com.baijiayun.live.ui.base.BasePadFragment
import com.baijiayun.live.ui.base.getViewModel
import com.baijiayun.live.ui.databinding.BjyLayoutPptMenuBinding
import com.baijiayun.live.ui.interactivepanel.InteractiveFragment
import com.baijiayun.live.ui.menu.rightmenu.RightMenuContract
import com.baijiayun.live.ui.pptpanel.handsuplist.HandsUpListFragment
import com.baijiayun.live.ui.pptpanel.handsuplist.PPTErrorDialog
import com.baijiayun.live.ui.pptpanel.popupwindow.DrawGraphPopupWindow
import com.baijiayun.live.ui.pptpanel.popupwindow.DrawWidthPopupWindow
import com.baijiayun.live.ui.pptpanel.popupwindow.DrawWordPopupWindow
import com.baijiayun.live.ui.speakerlist.item.*
import com.baijiayun.livecore.context.LPConstants
import com.baijiayun.livecore.context.LPConstants.ZXYBConnectStatus
import com.baijiayun.livecore.listener.OnPhoneRollCallListener
import com.baijiayun.livecore.models.LPAdminAuthModel
import com.baijiayun.livecore.models.LPAnswerModel
import com.baijiayun.livecore.models.LPBJTimerModel
import com.baijiayun.livecore.models.LPMotionEvent
import com.baijiayun.livecore.ppt.listener.OnPPTStateListener
import com.baijiayun.livecore.ppt.whiteboard.LaserShapeLayer
import com.baijiayun.livecore.utils.LPLogger
import com.baijiayun.livecore.utils.LPRxUtils
import com.baijiayun.livecore.wrapper.LPRecorder
import com.baijiayun.liveuibase.base.BaseUIConstant.SelectSrc
import com.baijiayun.liveuibase.toolbox.ToolboxWindow
import com.baijiayun.liveuibase.toolbox.bonuspoints.BonusPointsPopupWindow
import com.baijiayun.liveuibase.toolbox.zxyb.WritingboardWrapper
import com.baijiayun.liveuibase.toolbox.zxyb.WritingboardWrapper.ConnectStateCallback
import com.baijiayun.liveuibase.toolbox.zxyb.WritingboardWrapper.DeviceScanCallback
import com.baijiayun.liveuibase.utils.DisplayUtils
import com.baijiayun.liveuibase.utils.DisplayUtils.isPad
import com.baijiayun.liveuibase.utils.RxUtils
import com.baijiayun.liveuibase.utils.ThemeDataUtil
import com.baijiayun.liveuibase.utils.drawable.DrawableBuilder
import com.baijiayun.liveuibase.widgets.common.CheckImageView
import com.baijiayun.liveuibase.widgets.dialog.ThemeMaterialDialogBuilder
import com.baijiayun.liveuibase.widgets.popupwindow.BaseAutoArrangePopupWindow
import com.baijiayun.liveuibase.widgets.toolbar.*
import com.zxyb.zxybbaselib.ble.entity.BleDevice
import com.zxyb.zxybbaselib.ble.listener.XYScanDeviceCallback
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import kotlinx.android.synthetic.main.bjy_layout_ppt_menu.*
import kotlinx.android.synthetic.main.bjy_layout_ppt_menu.view.*
import kotlinx.android.synthetic.main.fragment_pad_ppt.*
import java.lang.ref.WeakReference
import java.util.concurrent.TimeUnit

/**
 * Created by Shubo on 2019-10-10.
 *
 */
class PPTFragment : BasePadFragment(), PPTMenuContract.View {
    private val pptViewModel by lazy {
        getViewModel { PPTViewModel(routerViewModel) }
    }
    private val handsUpListFragment by lazy {
        HandsUpListFragment.newInstance()
    }

    private val pptMenuLayout by lazy {
        LayoutInflater.from(context).inflate(R.layout.bjy_layout_ppt_menu, null)
    }
    private val pptView by lazy {
        context?.let {
            routerViewModel.pptViewData.value ?: MyPadPPTView(it, routerViewModel)
        }
    }
    private val navigateToMainObserver by lazy {
        Observer<Boolean> {
            if (it == true) {
                initSuccess()
            }
        }
    }
    private val presenter by lazy {
        PPTMenuPresenterBridge(
            this,
            (activity as LiveRoomBaseActivity).routerListener,
            routerViewModel
        )
    }

    private val motionEvent by lazy {
        LPMotionEvent()
    }

    private val toolboxWindow by lazy {
        val toolboxWindow = ToolboxWindow(context!!)
        toolboxWindow.setClickListener(object : ToolboxWindow.OnClickListener {
            override fun isClickable(): Boolean = checkClassStart()

            override fun onBrowserClick() {
            }

            override fun onSmallBlackboardClick() {
            }

            override fun onTimerClick() {
                routerViewModel.showTimer.value = true to LPBJTimerModel()
            }

            override fun onAnswererClick() {
                routerViewModel.answerStart.value = LPAnswerModel()
            }

            override fun onRedPacketClick() {
                routerViewModel.redPacketPublish.value = Unit
            }

            override fun onRollCallClick() {
                routerViewModel.showRollCall.value = -1 to null
            }

            override fun onResponderClick() {
                routerViewModel.showResponder.value = true
            }

            override fun onScreenShareClick() {
                routerViewModel.startScreenShare.value = Unit
            }
        })
        toolboxWindow.setOnDismissListener {
            pptMenuLayout.ivToolBox.isChecked = false
            pptMenuLayout.ivToolBox.background = if (pptMenuLayout.ivToolBox.isChecked) {
                ContextCompat.getDrawable(context!!, R.drawable.live_tool_bar_check_layer_bg)
            } else null
        }
        toolboxWindow
    }

    private val switch2FullScreenObserver by lazy {
        Observer<Pair<Boolean, Switchable?>> {
            it?.let {
                pptMenuLayout.apply {
                    ivQa.visibility = if (enableQaBtn()) View.VISIBLE else View.GONE
                    qaContainer.visibility = if (enableQaBtn()) View.VISIBLE else View.GONE
                    ivNotice.visibility = if (enableNoticeBtn()) View.VISIBLE else View.GONE
                    ivStudentHomeworkEntry.visibility =
                        if (enableStudentHomework()) View.VISIBLE else View.GONE
                    updateAVButtonVisibility()
                    ivFullScreen.isSelected = isFullScreen()
                    ivEyeCare.visibility = View.VISIBLE
                    reLayoutPPTMenu(it.first)
                    pptMenuLayout?.ivAsCameraStatus?.visibility =
                        if ((it.first || it.second?.switchableStatus == SwitchableStatus.MaxScreen)
                            && it.second is LocalItem && routerViewModel.liveRoom.speakQueueVM.enableAttachPhoneCamera()
                        ) View.VISIBLE else View.GONE
                    video_menu_iv.visibility = if (enableVideoMenuBtn()) View.VISIBLE else View.GONE
                }
                updateToolbarVisible()
                //切到全屏（替换container的view，退回时需要考虑还原问题）
                if (it.first) {
                    it.second?.run {
                        removeSwitchableFromParent(this)
                        if (switchableStatus != SwitchableStatus.MaxScreen) {
                            if (routerViewModel.switch2MaxScreen.value is LocalItem) {
                                (routerViewModel.switch2MaxScreen.value as LocalItem).invalidVideo()
                            }
                        }
                        //不走switchMaxScreen是为了保持变量不变用于还原
                        pptContainer.addView(
                            view,
                            FrameLayout.LayoutParams.MATCH_PARENT,
                            FrameLayout.LayoutParams.MATCH_PARENT
                        )
                    }
                } else {
                    //退出时，要考虑是不是从ppt区域切换过来，不是从ppt区域切换过来,avsdk重新绘制
                    it.second?.run {
                        if (switchableStatus != SwitchableStatus.MaxScreen) {
                            if (routerViewModel.switch2MaxScreen.value is LocalItem) {
                                (routerViewModel.switch2MaxScreen.value as LocalItem).invalidVideo()
                            }
                        }
                    }
                }
                checkWarmingupVideoPlaying()
            }
        }
    }

    private val switch2MaxScreenObserver by lazy {
        Observer<Switchable?> {
            it?.let {
                removeSwitchableFromParent(it)
                //有item在全屏，替换在maxScreen的位置
                var index = -1
                if (routerViewModel.switch2FullScreen.value?.first == true) {
                    index = (routerViewModel.switch2FullScreen.value?.second?.positionInParent
                        ?: 0) - 1
                }
                if (index < 0) {
                    pptContainer.addView(
                        it.view,
                        FrameLayout.LayoutParams.MATCH_PARENT,
                        FrameLayout.LayoutParams.MATCH_PARENT
                    )
                } else {
                    pptContainer.addView(
                        it.view,
                        index,
                        FrameLayout.LayoutParams(
                            FrameLayout.LayoutParams.MATCH_PARENT,
                            FrameLayout.LayoutParams.MATCH_PARENT
                        )
                    )
                }
                if (it.switchableType == SwitchableType.MainItem) {
                    routerViewModel.mainVideoItem = it
                }
                pptMenuLayout?.ivAsCameraStatus?.visibility =
                    if (it is LocalItem && routerViewModel.liveRoom.speakQueueVM.enableAttachPhoneCamera()) View.VISIBLE else View.GONE
                pptMenuLayout?.ivOperatePPT?.visibility =
                    if (enableOperateH5PPT()) View.VISIBLE else View.GONE
                //这时是切到max status没变，见switchToMaxScreen实现,用showPPTMenu()不准
                pptMenuLayout?.llPenMenu?.visibility =
                    if (it.itemType != SpeakItemType.PPT) View.GONE else View.VISIBLE
                if (it.itemType != SpeakItemType.PPT) {
                    clearLastCheckDrawItem()
                    presenter.changeDrawingStatus(ShapeChangeData(LPConstants.PPTEditMode.Normal))
                    pptMenuLayout?.video_menu_iv?.visibility =
                        if (enableVideoMenuBtn()) View.VISIBLE else View.GONE
                } else {
                    pptMenuLayout?.video_menu_iv?.visibility = View.GONE
                }
                checkWarmingupVideoPlaying()
            }
        }
    }

    private val animScale by lazy {
        ObjectAnimator.ofFloat(
            pptMenuLayout.left_container,
            "scaleX",
            pptMenuLayout.left_container.getScaleX(),
            0f
        )
    }
    private val animAlpha by lazy {
        ObjectAnimator.ofFloat(
            pptMenuLayout.left_container,
            "alpha",
            pptMenuLayout.left_container.alpha,
            0f
        )
    }

    private val animatorSet by lazy {
        val animatorSet = AnimatorSet()
        animatorSet.duration = 300
        animatorSet
    }

    private var isMenuExpand = true
    private var menuDataBinding: BjyLayoutPptMenuBinding? = null
    private var disposeOfClickable: Disposable? = null
    private var speakInviteDlg: MaterialDialog? = null
    private var forceSpeakDlg: MaterialDialog? = null
    private var pptErrorDialog: PPTErrorDialog? = null
    private var writingboardWrapper: WritingboardWrapper? = null
    private var eyeCareIsEnable: Boolean = false
    private var disposableOfBonusPointsTimer: Disposable? = null
    private var bonusPointPopupWindow: BonusPointsPopupWindow? = null

    override fun init(view: View) {
        // do nothing
    }

    @SuppressLint("ClickableViewAccessibility")
    private fun initView() {
        routerViewModel.pptViewData.value = pptView
        presenter.subscribe()
        menuDataBinding = DataBindingUtil.bind(pptMenuLayout)
        menuDataBinding?.let {
            it.pptviewmodel = this.pptViewModel
            it.lifecycleOwner = this@PPTFragment
        }
        pptMenuLayout.run {
            llPenMenu.background = DrawableBuilder()
                .solidColor(
                    ThemeDataUtil.getColorFromThemeConfigByAttrId(
                        context,
                        R.attr.base_theme_brand_container_color
                    )
                )
                .cornerRadius(context!!.resources.getDimensionPixelSize(R.dimen.bjy_base_common_bg_radius))
                .strokeWidth(DisplayUtils.dip2px(context!!, 1f))
                .strokeColor(ContextCompat.getColor(context!!, R.color.base_bg_stroke_10))
                .build()

            view_roll_call_going.background = DrawableBuilder()
                .solidColor(
                    ThemeDataUtil.getColorFromThemeConfigByAttrId(
                        context,
                        R.attr.base_theme_live_product_color
                    )
                )
                .oval()
                .build()
            //学生没有同意举手的按钮,把音视频按钮放举手左边
            if (!pptViewModel.isTeacherOrAssistant()) {
                if (media_container.layoutParams is ConstraintLayout.LayoutParams) {
                    val layoutParams = media_container.layoutParams as ConstraintLayout.LayoutParams
                    layoutParams.endToStart = R.id.rlSpeakWrapper
                }
            }
            updateAVButtonVisibility()
            ivFullScreen.visibility = View.VISIBLE
            ivFullScreen.isSelected = isFullScreen()
            ivFullScreen.setOnClickListener {
                if (isFullScreen()) {
                    routerViewModel.switch2FullScreen.value?.second?.run {
                        switchToFullScreen(false)
                    }
                } else {
                    routerViewModel.switch2MaxScreen.value?.run {
                        switchToFullScreen(true)
                    }
                }
            }
            //工具箱
            ivToolBox.setOnClickListener {
                changePopupWindowState(toolboxWindow, ivToolBox)
                ivToolBox.isChecked = true
                ivToolBox.background = if (ivToolBox.isChecked) {
                    ContextCompat.getDrawable(context!!, R.drawable.live_tool_bar_check_layer_bg)
                } else null
            }
            ivHandsUpImg.setOnClickListener {
                showDialogFragment(handsUpListFragment)
                pptViewModel.hasRead.value = true
            }
            // region 画笔选择事件逻辑
            ciSelect.setOnClickListener {
                onToolbarItemClick(
                    ciSelect,
                    ShapeChangeData(LPConstants.PPTEditMode.SelectMode),
                    null
                )
            }
            ciPen.setOnClickListener {
                onToolbarItemClick(
                    ciPen,
                    ShapeChangeData(
                        SelectSrc.Brush,
                        LPConstants.PPTEditMode.ShapeMode,
                        LPConstants.ShapeType.Doodle
                    ),
                    brushPopupWindow
                )
            }
            ciMark.setOnClickListener {
                onToolbarItemClick(
                    ciMark,
                    ShapeChangeData(
                        SelectSrc.Marker,
                        LPConstants.PPTEditMode.ShapeMode,
                        LPConstants.ShapeType.MarkerDoodle
                    ),
                    markerPopupWindow
                )
            }
            graphPopupWindow = DrawGraphPopupWindow(context, routerViewModel)
            ciGraph.setOnClickListener {
                if (graphShapeCache != null) {
                    onToolbarItemClick(
                        ciGraph,
                        ShapeChangeData(
                            SelectSrc.Graph,
                            LPConstants.PPTEditMode.ShapeMode,
                            graphShapeCache
                        ),
                        graphPopupWindow
                    )
                }
            }
            // 文字画笔 输入框
            val gestureDetector = GestureDetector(context, object : SimpleOnGestureListener() {
                override fun onDown(e: MotionEvent): Boolean {
                    if (!presenter.isEnableDrawing()) {
                        return false
                    }
                    textEditFrameLayout.setEditText("")
                    val drawShapeData = routerViewModel.actionNavigateToPPTDrawing.value
                    if (drawShapeData?.pptEditMode != LPConstants.PPTEditMode.ShapeMode
                        || drawShapeData.shapeType != LPConstants.ShapeType.Text
                    ) {
                        return false
                    }
                    val info = LaserShapeLayer.PositionInfo()
                    pptView?.run {
                        getPPTPagePositionInfo(info)
                        if (e.y < top + info.offsetHeight || e.y > bottom - info.offsetHeight ||
                            e.x < left + info.offsetWidth || e.x > right - info.offsetWidth
                        ) {
                            return false
                        }
                    }
                    // 调起输入框
                    textEditContainer.removeAllViews()
                    textEditContainer.addView(textEditFrameLayout.view)
                    return false
                }
            })
            setOnTouchListener { _, event -> gestureDetector.onTouchEvent(event) }
            ciWord.setOnClickListener {
                onToolbarItemClick(
                    ciWord,
                    ShapeChangeData(
                        SelectSrc.Text,
                        LPConstants.PPTEditMode.ShapeMode,
                        LPConstants.ShapeType.Text
                    ),
                    wordPopupWindow
                )
            }
            laserShapeLayer
            ciLaser.setOnClickListener {
                onToolbarItemClick(ciLaser, ShapeChangeData(LPConstants.PPTEditMode.Normal), null)
            }
            ciPenClear.setOnClickListener {
                if (isEraseMode) {
                    onToolbarItemClick(
                        ciPenClear,
                        ShapeChangeData(LPConstants.PPTEditMode.EraserMode),
                        null
                    )
                } else {
                    pptView?.run {
                        eraseShapes()
                    }
                }
                updateEraserMode(true)
            }
            // endregion
            // region 默认画笔属性
            for (selectSrc in SelectSrc.values()) {
                updateToolbarPreviewColor(selectSrc, defaultDrawColor)
                colorSelectCache[selectSrc] = defaultDrawColor
            }
            widthSelectCache[SelectSrc.Brush] = BaseDrawWidthSettingWindow.pencilPaintSize[1]
            widthSelectCache[SelectSrc.Marker] = BaseDrawWidthSettingWindow.markerPaintSize[1]
            // endregion
            tvPPTFiles.setOnClickListener {
                routerViewModel.actionShowPPTManager.value = true
            }
            ivNotice.setOnClickListener {
                routerViewModel.actionShowAnnouncementFragment.value = true
            }
            double_teacher_class_change_iv.visibility =
                if (routerViewModel.liveRoom.enableSwitchClass()) View.VISIBLE else View.GONE
            double_teacher_class_change_iv.isSelected = routerViewModel.liveRoom.isAllInParentRoom

            ivQa.visibility = if (enableQaBtn()) View.VISIBLE else View.GONE
            qaContainer.visibility = if (enableQaBtn()) View.VISIBLE else View.GONE
            ivQa.setOnClickListener {
                routerViewModel.actionShowQAInteractiveFragment.value = Unit
                routerViewModel.hasNewQa.value = false
            }
            if (routerViewModel.isShowEyeCare.value != null) {
                eyeCareIsEnable = routerViewModel.isShowEyeCare.value!!
            }
            ivEyeCare.setImageDrawable(
                ContextCompat.getDrawable(
                    context, if (eyeCareIsEnable) {
                        R.drawable.icon_eye_care_checked
                    } else R.drawable.icon_eye_care_normal
                )
            )
            ivEyeCare.setOnClickListener {
                eyeCareIsEnable = !eyeCareIsEnable
                routerViewModel.isShowEyeCare.value = eyeCareIsEnable
                ivEyeCare.setImageDrawable(
                    ContextCompat.getDrawable(
                        context,
                        if (eyeCareIsEnable) R.drawable.icon_eye_care_checked
                        else R.drawable.icon_eye_care_normal
                    )
                )
            }
            ivStudentHomeworkEntry.visibility =
                if (enableStudentHomework()) View.VISIBLE else View.GONE
            ivStudentHomeworkEntry.setOnClickListener {
                routerViewModel.actionShowPPTManager.value = true
            }
            ivNotice.visibility = if (enableNoticeBtn()) View.VISIBLE else View.GONE
            ivOperatePPT.visibility = if (enableOperateH5PPT()) View.VISIBLE else View.GONE
            ivAsCameraStatus.visibility = if (enableAsCamera()) View.VISIBLE else View.GONE
            writingboard_ble_container.visibility =
                if (enableWritingboard()) View.VISIBLE else View.GONE
            //学生隐藏操作摄像头按钮
            if (liveHideStudentCamera()) {
                tvVideo.visibility = View.GONE
            }
            ivPPTAuth.setOnClickListener {
                clearLastCheckDrawItem(false)
                ivPPTAuth.isChecked = !ivPPTAuth.isChecked
                ivPPTAuth.background = if (ivPPTAuth.isChecked) {
                    ContextCompat.getDrawable(context!!, R.drawable.live_tool_bar_check_layer_bg)
                } else null
                val pptModel =
                    if (ivPPTAuth.isChecked) LPConstants.PPTEditMode.PPTTouchMode else LPConstants.PPTEditMode.Normal
                presenter.changeDrawingStatus(ShapeChangeData(pptModel))
            }
            ivOperatePPT.setOnClickListener {
                if (routerViewModel.liveRoom.studentSwitchPPTState) {
                    showToastMessage(getString(R.string.bjy_live_operate_ppt_fail_tip))
                    return@setOnClickListener
                }
                if (!routerViewModel.liveRoom.hasH5PPTAuth()) {
                    routerViewModel.liveRoom.requestH5PPTAuth(true)
                } else {
                    pptView?.showH5PPTAuthDialog(false)
                }
            }
            ivAsCameraStatus.setOnClickListener {
                if (routerViewModel.liveRoom.speakQueueVM.isReplacedUser) {
                    if (routerViewModel.mainVideoItem is LocalItem) {
                        (routerViewModel.mainVideoItem as LocalItem).endScannerCamera()
                    }
                } else {
                    if (routerViewModel.mainVideoItem is LocalItem) {
                        (routerViewModel.mainVideoItem as LocalItem).startScannerCamera()
                    }
                }
            }
            video_menu_iv.setOnClickListener {
                val maxScreenItem = routerViewModel.switch2MaxScreen.value
                if (maxScreenItem is BaseSwitchItem) {
                    maxScreenItem.showOptionDialog()
                }
            }

            compositeDisposable.add(RxUtils.clicks(tvVideo).throttleFirst(1, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    if (routerViewModel.isClassStarted.value != true) {
                        showToastMessage(getString(R.string.pad_class_start_tip))
                        return@subscribe
                    }
                    if (!clickableCheck()) {
                        showToastMessage(getString(R.string.live_frequent_error))
                    } else {
                        presenter.changeVideo()
                    }
                })

            compositeDisposable.add(RxUtils.clicks(tvAudio).throttleFirst(1, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    if (routerViewModel.isClassStarted.value != true) {
                        showToastMessage(getString(R.string.pad_class_start_tip))
                        return@subscribe
                    }
                    if (!clickableCheck()) {
                        showToastMessage(getString(R.string.live_frequent_error))
                    } else {
                        presenter.changeAudio()
                    }
                })

            compositeDisposable.add(RxUtils.clicks(tvSpeakApply).throttleFirst(1, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    if (routerViewModel.isClassStarted.value != true) {
                        showToastMessage(getString(R.string.live_hand_up_error))
                        return@subscribe
                    }
                    if (!clickableCheck()) {
                        showToastMessage(getString(R.string.live_frequent_error))
                    } else {
                        if (!presenter.isWaitingRecordOpen) {
                            presenter.speakApply()
                        }
                    }
                })

            compositeDisposable.add(RxUtils.clicks(double_teacher_class_change_iv).throttleFirst(1, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    ThemeMaterialDialogBuilder(context)
                        .title("")
                        .content(
                            if (!routerViewModel.liveRoom.isGroupTeacherSwitchRoom) {
                                R.string.bjy_live_switch_room_yes_or_no
                            } else {
                                if (routerViewModel.liveRoom.isAllInParentRoom) {
                                    R.string.bjy_live_switch_group_room_yes_or_no
                                } else {
                                    R.string.bjy_live_switch_parent_room_yes_or_no
                                }
                            }
                        )
                        .positiveText(R.string.base_live_confirm)
                        .negativeText(R.string.base_live_cancel)
                        .widgetColor(
                            ThemeDataUtil.getColorFromThemeConfigByAttrId(
                                context,
                                R.attr.base_theme_live_product_color
                            )
                        )
                        .positiveColor(
                            ThemeDataUtil.getColorFromThemeConfigByAttrId(
                                context,
                                R.attr.base_theme_live_product_color
                            )
                        )
                        .negativeColor(ContextCompat.getColor(context, R.color.base_warning_color))
                        .onPositive { dialog: MaterialDialog, _: DialogAction? ->
                            routerViewModel.liveRoom.requestSwitchClass()
                            dialog.dismiss()
                        }
                        .show()
                })

            compositeDisposable.add(routerViewModel.liveRoom.observableOfClassSwitchState
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    double_teacher_class_change_iv.isSelected = !double_teacher_class_change_iv.isSelected
                })

            when (routerViewModel.liveRoom.currentUser.type) {
                LPConstants.LPUserType.Teacher -> {
                    rlSpeakWrapper.visibility = View.GONE
                }
                LPConstants.LPUserType.Assistant -> {
                    rlSpeakWrapper.visibility = View.GONE
                }
                else -> {
                    tvPPTFiles.visibility = View.GONE
                    tvHandsUpCount.visibility = View.GONE
                    ivHandsUpImg.visibility = View.GONE
                    if (!routerViewModel.liveRoom.hasStudentRaise()) {
                        rlSpeakWrapper.visibility = View.GONE
                    }
                }
            }
            if (routerViewModel.liveRoom.isMockLive || routerViewModel.liveRoom.isPushLive) {
                rlSpeakWrapper.visibility = View.GONE
            }
        }

        pptView?.run {
            if (!isInFullScreen) {
                switchToMaxScreen()
            }
            checkSyncPPTVideo()
        }
        //fix 'The specified child already has a parent'bug.
        //断线重连和重进，内存异常重启都已经移除了fragment
        //这么处理暂时规避问题，toolbars 是lazy的跟随this对象（尽量不用lazy）
        removeViewFromParent(pptMenuLayout)
        menuContainer.addView(
            pptMenuLayout,
            FrameLayout.LayoutParams.MATCH_PARENT,
            FrameLayout.LayoutParams.MATCH_PARENT
        )
        pptMenuLayout.post {
            reLayoutPPTMenu(false)
            if (routerViewModel.liveRoom.currentUser.type == LPConstants.LPUserType.Assistant) {
                showAssistantMenu(routerViewModel.liveRoom.adminAuth)
            }
        }
        checkWarmingupVideoPlaying()
        bonus_points_iv.setOnClickListener {
            routerViewModel.actionShowBonusPointsWindow.value =
                if (routerViewModel.actionShowBonusPointsWindow.value == null) true
                else {
                    !routerViewModel.actionShowBonusPointsWindow.value!!
                }
        }
        bonus_points_iv.visibility = if (enableBonusPoints()) View.VISIBLE else View.GONE
        compositeDisposable.add(RxUtils.clicks(menu_expand_iv)
            .throttleFirst(400, TimeUnit.MILLISECONDS)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                startExpandAnim()
            })
        compositeDisposable.add(routerViewModel.liveRoom.toolBoxVM.observableOfBonusPointsAdd
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                bonusPointPopupWindow?.dismiss()
                bonusPointPopupWindow = BonusPointsPopupWindow(context!!, it)
                bonusPointPopupWindow!!.run {
                    setOnDismissListener {
                        LPRxUtils.dispose(disposableOfBonusPointsTimer)
                    }
                    show(bonus_points_iv)
                    LPRxUtils.dispose(disposableOfBonusPointsTimer)
                    disposableOfBonusPointsTimer = Observable.timer(2, TimeUnit.SECONDS)
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe {
                            bonusPointPopupWindow?.dismiss()
                        }
                }
            })

        compositeDisposable.add(routerViewModel.liveRoom.toolBoxVM.observableOfBonusPointsRemainUpdate
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                if (!it.success) {
                    showToastMessage(getString(R.string.base_bouns_points_not_enough_tip))
                }
            })

        animatorSet.addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator?) {
                if (isMenuExpand) {
                    pptMenuLayout.left_container.visibility = View.VISIBLE
                }
            }

            override fun onAnimationEnd(animation: Animator?) {
                if (!isMenuExpand) {
                    pptMenuLayout.left_container.visibility = View.GONE
                }
            }

            override fun onAnimationCancel(animation: Animator?) {
                // do nothing
            }

            override fun onAnimationRepeat(animation: Animator?) {
                // do nothing
            }
        })
    }

    private fun startExpandAnim() {
        animatorSet.cancel()
        pptMenuLayout.left_container.pivotX = 0f
        if (isMenuExpand) {
            animScale.setFloatValues(pptMenuLayout.left_container.getScaleX(), 0f)
            animAlpha.setFloatValues(pptMenuLayout.left_container.alpha, 0f)
        } else {
            animScale.setFloatValues(pptMenuLayout.left_container.getScaleX(), 1f)
            animAlpha.setFloatValues(pptMenuLayout.left_container.alpha, 1f)
        }
        animatorSet.play(animScale).with(animAlpha)
        pptMenuLayout.menu_expand_iv.isSelected = isMenuExpand
        isMenuExpand = !isMenuExpand
        animatorSet.start()
    }

    private fun liveHideStudentCamera() =
        !routerViewModel.liveRoom.isTeacherOrAssistant && !routerViewModel.liveRoom.isGroupTeacherOrAssistant &&
                routerViewModel.liveRoom.partnerConfig.liveHideStudentCamera == 1

    override fun observeActions() {
        routerViewModel.actionNavigateToMain.observeForever(navigateToMainObserver)
    }

    private fun initSuccess() {
        pptView?.run {
            attachLiveRoom(routerViewModel.liveRoom)
            start()
            setOnPPTStateListener(object : OnPPTStateListener {
                override fun onSuccess(code: Int, successMessage: String) {
                    if (code == OnPPTStateListener.CODE_PPT_WHITEBOARD_ADD) {
                        pptView?.switchPPTPage("0", Integer.valueOf(successMessage))
                    }
                }

                override fun onError(code: Int, errorMessage: String) {
                    showMessage(errorMessage)
                }
            })
            initPPTViewObserve()
            if (routerViewModel.liveRoom.isTeacherOrAssistant || routerViewModel.liveRoom.isGroupTeacherOrAssistant) {
                setRemarksEnable(true)
            }
        }
        // 选择模式，橡皮擦 <-> 垃圾桶，功能变更
        pptView?.setOnShapeSelectedListener { selected -> updateEraserMode(!selected) }
        initView()
        initZXYBSDK()
    }

    // region 权限
    private fun enableQaBtn() =
        if (routerViewModel.liveRoom.roomType == LPConstants.LPRoomType.OneOnOne || isFullScreen()) {
            false
        } else {
            if (isTeacherOrAssistant()) {
                routerViewModel.liveRoom.partnerConfig.enableLiveQuestionAnswer == 1 &&
                        !routerViewModel.liveRoom.partnerConfig.liveFeatureTabs.isNullOrEmpty() &&
                        routerViewModel.liveRoom.partnerConfig.liveFeatureTabs.split(",")
                            .contains(InteractiveFragment.LABEL_ANSWER)
            } else {
                routerViewModel.liveRoom.partnerConfig.enableLiveQuestionAnswer == 1 &&
                        !routerViewModel.liveRoom.partnerConfig.liveStudentFeatureTabs.isNullOrEmpty() &&
                        routerViewModel.liveRoom.partnerConfig.liveStudentFeatureTabs.split(",")
                            .contains(InteractiveFragment.LABEL_ANSWER)
            }
        }

    private fun enableStudentHomework() = !routerViewModel.liveRoom.isTeacherOrAssistant
            && !routerViewModel.liveRoom.isGroupTeacherOrAssistant
            && routerViewModel.liveRoom.partnerConfig.enableUseHomeWork == 1

    private fun enableOperateH5PPT() =
        routerViewModel.canOperateH5PPT() && (isFullScreen() || routerViewModel.switch2MaxScreen.value?.itemType == SpeakItemType.PPT)

    private fun enableNoticeBtn() =
        routerViewModel.liveRoom.roomType != LPConstants.LPRoomType.OneOnOne && !isFullScreen()

    private fun enableVideoMenuBtn() =
        !isFullScreen() && routerViewModel.switch2MaxScreen.value?.itemType != SpeakItemType.PPT

    private fun isFullScreen() = routerViewModel.switch2FullScreen.value?.first == true

    private fun clickableCheck(): Boolean {
        if (disposeOfClickable != null && !disposeOfClickable!!.isDisposed) {
            return false
        }
        disposeOfClickable =
            Observable.timer(1, TimeUnit.SECONDS).subscribe { RxUtils.dispose(disposeOfClickable) }
        return true
    }

    //只支持主讲分享二维码
    private fun enableAsCamera(): Boolean {
        //在全屏或者课件区显示
        return routerViewModel.liveRoom.speakQueueVM.enableAttachPhoneCamera() && (routerViewModel.mainVideoItem?.isInFullScreen == true
                || routerViewModel.mainVideoItem?.switchableStatus == SwitchableStatus.MaxScreen)
    }

    private fun enableWritingboard() = routerViewModel.liveRoom.zxybvm.enableUseHandWritingBoard()
            && (routerViewModel.liveRoom.zxybvm.connectType != LPConstants.ZXYBConnectType.TYPE_BLE
            || routerViewModel.liveRoom.zxybvm.recentBleDevices.isNotEmpty())

    private fun enableDrawingAuth() =
        isAdmin(routerViewModel.liveRoom) || routerViewModel.liveRoom.speakQueueVM.drawingAuth
                || (routerViewModel.speakApplyStatus.value == RightMenuContract.STUDENT_SPEAK_APPLY_SPEAKING
                && routerViewModel.liveRoom.partnerConfig.liveDisableGrantStudentBrush == 1)

    private fun enableSwitchPPT() =
        isAdmin(routerViewModel.liveRoom) || !routerViewModel.liveRoom.studentSwitchPPTState

    private fun enableWarmingupVideo() =
        routerViewModel.liveRoom.speakQueueVM.enableWarmingUpVideo()
                && !routerViewModel.liveRoom.isClassStarted
                && if (isFullScreen()) routerViewModel.switch2FullScreen.value?.second?.switchableType == SwitchableType.MainItem
        else routerViewModel.switch2MaxScreen.value?.switchableType == SwitchableType.MainItem

    private fun enableBonusPoints() = routerViewModel.liveRoom.toolBoxVM.enableUseBonusPoints()
    // endregion
    /**
     * 暖场视频隐藏底部icon
     */

    /**
     * 暖场视频隐藏底部icon
     */
    private fun checkWarmingupVideoPlaying() {
        if (enableWarmingupVideo()) {
            hideBottomMenu()
        } else {
            showBottomMenu()
        }
    }

    /**
     * 手机端布局调整
     * 正常情况下在音视频按钮上24dp位置
     * 全屏时显示在右上位置
     */
    private fun reLayoutPPTMenu(showTop: Boolean? = true) = context?.apply {
        if (!isPad(this)) {
            val layoutParams = ConstraintLayout.LayoutParams(
                ConstraintLayout.LayoutParams.WRAP_CONTENT,
                ConstraintLayout.LayoutParams.WRAP_CONTENT
            )
            if (showTop != true) {
                layoutParams.rightToRight = ConstraintSet.PARENT_ID
                layoutParams.bottomToBottom = ConstraintSet.PARENT_ID
                layoutParams.topToTop = ConstraintSet.UNSET
                layoutParams.bottomMargin =
                    resources.getDimensionPixelSize(R.dimen.ppt_menu_margin_bottom) + pptMenuLayout.ivFullScreen.measuredHeight
                layoutParams.rightMargin =
                    resources.getDimensionPixelSize(R.dimen.ppt_menu_widget_root_margin)
            } else {
                layoutParams.topToTop = ConstraintSet.PARENT_ID
                layoutParams.rightToRight = ConstraintSet.PARENT_ID
                layoutParams.bottomToBottom = ConstraintSet.UNSET
                layoutParams.topMargin =
                    resources.getDimensionPixelSize(R.dimen.ppt_menu_widget_root_margin)
                layoutParams.rightMargin =
                    resources.getDimensionPixelSize(R.dimen.ppt_menu_widget_root_margin)
            }
            pptMenuLayout.llPenMenu.layoutParams = layoutParams
        }
    }

    // region toolbar 画笔逻辑
    /**
     * 启用时调用此方法以检查 ppt 状态，如果不在黑板区则恢复至黑板区
     */
    private fun checkAndResetInSync(pptView: MyPadPPTView): Boolean {
        pptView.run {
            //不能用isFullScreen判断是不是全屏中
            if (switchableStatus != SwitchableStatus.MaxScreen && routerViewModel.switch2FullScreen.value?.first != true) {
                switchPPTVideoWithoutSync(true)
                return true
            }
            return false
        }
    }

    private var lastCheckedDrawItem: CheckImageView? = null

    /**
     * toolbar 画笔点击
     */
    private fun onToolbarItemClick(
        itemView: CheckImageView,
        shapeChangeData: ShapeChangeData,
        popupWindow: BaseAutoArrangePopupWindow?
    ) {
        if (!itemView.isChecked) {
            // 启用画笔
            presenter.changeDrawing(shapeChangeData)
            // 弹窗
            if (presenter.canStudentDraw()) {
                changePopupWindowState(popupWindow, itemView)
            }
        } else {
            presenter.changeDrawing(ShapeChangeData(LPConstants.PPTEditMode.Normal))
        }
        if (presenter.canStudentDraw()) {
            updateToolbarItemCheck(itemView, !itemView.isChecked)
            laserShapeLayer.enableDrawLaser(ciLaser.isChecked)
        }
    }

    private fun updateToolbarItemCheck(itemView: View, newStatus: Boolean) {
        if (itemView !is CheckImageView) {
            return
        }
        // region 更新自身为选中状态
        itemView.isChecked = newStatus
        itemView.background = if (newStatus && itemView != ciGraph) {
            ContextCompat.getDrawable(context!!, R.drawable.live_tool_bar_check_layer_bg)
        } else null
        // endregion

        // region 检查并更新上一个选中的 view
        if (newStatus && lastCheckedDrawItem != itemView) {
            clearLastCheckDrawItem()
            lastCheckedDrawItem = itemView
        } else if (!newStatus) {
            clearLastCheckDrawItem()
        }
        // endregion
    }

    private fun resetToolbar() {
        if (lastCheckedDrawItem != null) {
            onToolbarItemClick(
                lastCheckedDrawItem!!,
                ShapeChangeData(LPConstants.PPTEditMode.Normal),
                null
            )
        }
        changePopupWindowState(brushPopupWindow, null)
        changePopupWindowState(markerPopupWindow, null)
        changePopupWindowState(wordPopupWindow, null)
        if (::graphPopupWindow.isInitialized) {
            changePopupWindowState(graphPopupWindow, null)
        }
    }

    private fun clearLastCheckDrawItem(pptAuth: Boolean? = true) {
        if (lastCheckedDrawItem != null) {
            lastCheckedDrawItem!!.isChecked = false
            lastCheckedDrawItem!!.background = null
            lastCheckedDrawItem = null
        }
        if (pptMenuLayout.ivPPTAuth.isChecked && pptAuth != false) {
            pptMenuLayout.ivPPTAuth.isChecked = false
            pptMenuLayout.ivPPTAuth.background = null
        }
    }

    // key - 画笔模式, value - 对应颜色
    private val colorSelectCache = HashMap<SelectSrc, Int>()

    // key - 画笔模式, value - 宽度
    private val widthSelectCache = HashMap<SelectSrc, Float>()

    // 图形模式 缓存
    private var graphShapeCache: LPConstants.ShapeType? = null

    // 橡皮擦状态：Eraser <--> Delete
    private var isEraseMode = true

    private val brushPopupWindow by lazy { DrawWidthPopupWindow(false, context!!, routerViewModel) }
    private val markerPopupWindow by lazy { DrawWidthPopupWindow(true, context!!, routerViewModel) }
    private lateinit var graphPopupWindow: DrawGraphPopupWindow
    private val wordPopupWindow by lazy { DrawWordPopupWindow(context!!, routerViewModel) }

    /**
     * 切换PopupWindow状态
     *
     * @param popupWindow popupWindow
     * @param anchor      为空则隐藏 popupWindow
     */
    private fun changePopupWindowState(popupWindow: BaseAutoArrangePopupWindow?, anchor: View?) {
        if (popupWindow == null) {
            return
        }
        if (anchor != null && !popupWindow.isShowing) {
            popupWindow.initLimitView(WeakReference(this.pptMenuLayout))
            popupWindow.show(anchor)
            return
        }
        if (anchor == null && popupWindow.isShowing) {
            popupWindow.dismiss()
        }
    }

    private val defaultDrawColor = Color.parseColor("#1795FF")

    /**
     * 更新预览颜色
     */
    private fun updateToolbarPreviewColor(selectSrc: SelectSrc, color: Int) {
        when (selectSrc) {
            SelectSrc.Brush -> pptMenuLayout.ciPenPreview
            SelectSrc.Marker -> pptMenuLayout.ciMarkPreview
            SelectSrc.Graph -> pptMenuLayout.ciGraphPreview
            SelectSrc.Text -> pptMenuLayout.ciWordPreview
        }.background = getPreviewDrawable(color)
    }

    /**
     * 更新橡皮擦状态
     */
    private fun updateEraserMode(isEraseMode: Boolean) {
        this.isEraseMode = isEraseMode
        if (!isEraseMode) {
            pptMenuLayout.ciPenClear.setCheckedDrawable(
                ContextCompat.getDrawable(
                    context!!,
                    R.drawable.base_ic_toolbar_delete_select
                )
            )
            pptMenuLayout.ciPenClear.setUnCheckedDrawable(
                ContextCompat.getDrawable(
                    context!!,
                    R.drawable.base_ic_toolbar_delete_normal
                )
            )
        } else {
            pptMenuLayout.ciPenClear.setCheckedDrawable(
                ContextCompat.getDrawable(
                    context!!,
                    R.drawable.base_ic_toolbar_erase_select
                )
            )
            pptMenuLayout.ciPenClear.setUnCheckedDrawable(
                ContextCompat.getDrawable(
                    context!!,
                    R.drawable.base_ic_toolbar_erase_normal
                )
            )
        }
    }

    private fun hideBottomMenu() {
        if (routerViewModel.liveRoom.speakQueueVM.enableWarmingUpVideo() != true) {
            return
        }
        pptMenuLayout.run {
            right_container.visibility = View.GONE
            menu_expand_iv.visibility = View.GONE
            left_container.visibility = View.GONE
        }
    }

    private fun showBottomMenu() {
        if (routerViewModel.liveRoom.speakQueueVM.enableWarmingUpVideo() != true) {
            return
        }
        pptMenuLayout.run {
            right_container.visibility = View.VISIBLE
            menu_expand_iv.visibility = View.VISIBLE
            left_container.visibility = View.VISIBLE
        }
    }

    /**
     * 获取预览颜色 Drawable
     */
    private fun getPreviewDrawable(color: Int): Drawable {
        return ColorDrawable(color)
    }

    private val laserShapeLayer by lazy {
        val laserShapeLayer = LaserShapeLayer(context)
        laserShapeLayer.bringToFront()
        laserContainer.addView(
            laserShapeLayer,
            ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
            )
        )
        laserShapeLayer.setOnChangeLaserShapeListener {
            it.isFull = isFullScreen()
            pptView?.getPPTPagePositionInfo(it)
        }

        laserShapeLayer.setLiveRoom(routerViewModel.liveRoom)
        laserShapeLayer
    }

    private val textEditFrameLayout by lazy {
        TextEditFrameLayout(context, TextEditFrameLayout.IOnTextChangeListener {
            if (it["end"] != "true") {
                pptView?.sendDrawTextConfirmed(
                    it["beforeText"] as String,
                    it["afterText"] as String
                )
            } else {
                pptView?.invalidateCurrentPage()
                textEditContainer.removeAllViews()
            }
        })
    }
    // endregion

    private fun initPPTViewObserve() {
        routerViewModel.run {
            notifyPPTPageCurrent.observe(this@PPTFragment, Observer {
                it?.run {
                    pptView?.updatePage(it, true, false)
                }
            })
            addPPTWhiteboardPage.observe(this@PPTFragment, Observer {
                it?.run {
                    pptView?.addPPTWhiteboardPage()
                }
            })
            deletePPTWhiteboardPage.observe(this@PPTFragment, Observer {
                it?.run {
                    pptView?.deletePPTWhiteboardPage(it)
                }
            })
            changePPTPage.observe(this@PPTFragment, Observer {
                it?.run {
                    pptView?.switchPPTPage(it.first, it.second)
                }
            })
            // region 画笔相关监听
            // 画笔变更
            actionNavigateToPPTDrawing.observe(this@PPTFragment, Observer {
                it?.let {
                    pptView?.run {
                        // 切换画笔模式
                        pptEditMode = it.pptEditMode
                        if (it.isNeedInvalidate) {
                            textEditContainer.removeAllViews()
                            invalidateCurrentPage()
                        }
                        if (it.pptEditMode == LPConstants.PPTEditMode.Normal || it.pptEditMode == LPConstants.PPTEditMode.PPTTouchMode) {
                            return@Observer
                        }
                        checkAndResetInSync(pptView!!)
                        if (it.pptEditMode != LPConstants.PPTEditMode.SelectMode) {
                            setShapeType(it.shapeType)
                            // 检查画笔颜色缓存
                            if (colorSelectCache.containsKey(it.selectSrc)) {
                                setPaintColor(colorSelectCache[it.selectSrc]!!)
                            }
                            // 检查画笔宽度缓存
                            if (it.selectSrc != SelectSrc.Graph && widthSelectCache.containsKey(it.selectSrc)) {
                                setShapeStrokeWidth(widthSelectCache[it.selectSrc]!!)
                            }
                        }
                    }
                }
            })
            // 画笔颜色变更
            drawColorChange.observe(this@PPTFragment, Observer {
                it?.let {
                    // 加入缓存
                    colorSelectCache[it.selectSrc] = it.selectColor
                    // 更新画笔颜色
                    pptView?.setPaintColor(it.selectColor)
                    // 更新预览颜色
                    updateToolbarPreviewColor(it.selectSrc, it.selectColor)
                }
            })
            // 画笔宽度变更
            drawWidthChange.observe(this@PPTFragment, Observer {
                it?.let {
                    if (it.selectSrc != SelectSrc.Graph) {
                        // 加入缓存
                        widthSelectCache[it.selectSrc] = it.width
                        // 更新画笔宽度
                        pptView?.setShapeStrokeWidth(it.width)
                    } else {
                        // 自定义图形画笔宽度
                        pptView?.setCustomShapeStrokeWidth(it.width)
                    }
                }
            })
            // 自定义图形变更
            drawGraphChange.observe(this@PPTFragment, Observer {
                it?.let {
                    pptMenuLayout.ciGraph.setCheckedDrawable(it.selectDrawable)
                    pptMenuLayout.ciGraph.setUnCheckedDrawable(it.normalDrawable)
                    graphShapeCache = it.shapeType
                    if (it.isInitDrawable) {
                        return@let
                    }
                    pptView?.run {
                        pptEditMode = LPConstants.PPTEditMode.ShapeMode
                        setShapeType(it.shapeType)
                    }
                }
            })
            drawTextSizeChange.observe(this@PPTFragment, Observer {
                it?.let {
                    pptView?.setPaintTextSize(it)
                }
            })
            editTextShape.observe(this@PPTFragment, Observer {
                it?.let {
                    val shapeChangeData =
                        ShapeChangeData(
                            SelectSrc.Text,
                            LPConstants.PPTEditMode.ShapeMode,
                            LPConstants.ShapeType.Text
                        )
                    shapeChangeData.isNeedInvalidate = false
                    actionNavigateToPPTDrawing.value = shapeChangeData
                    updateToolbarItemCheck(ciWord, true)

                    textEditContainer.removeAllViews()
                    textEditContainer.addView(textEditFrameLayout.view)
                    textEditFrameLayout.setEditText(it)
                }
            })
            // endregion
            //ppt全屏不要公告问答和摄像头音频,视频全屏时，只有举手按钮
            switch2FullScreen.observeForever(switch2FullScreenObserver)
            switch2MaxScreen.observeForever(switch2MaxScreenObserver)
            isClassStarted.observe(this@PPTFragment, Observer {
                if (it == true) {
                    showMessage(
                        getString(
                            R.string.live_message_le,
                            getString(R.string.lp_override_class_start)
                        )
                    )
                    if (isAutoSpeak() && liveRoom.currentUser.type == LPConstants.LPUserType.Student && !liveRoom.isAudition) {
                        showAutoSpeak(liveRoom.partnerConfig.liveDisableGrantStudentBrush == 1)
                    }
                    showBottomMenu()
                } else {
                    hideBottomMenu()
                }
            })
            classEnd.observe(this@PPTFragment, Observer {
                it?.let {
                    showMessage(
                        getString(
                            R.string.live_message_le,
                            getString(R.string.lp_override_class_end)
                        )
                    )
                    routerViewModel.exitFullScreen()
                }
            })
            action2PPTError.observe(this@PPTFragment, Observer {
                it?.let {
                    if (!canShowDialog()) return@Observer
                    try {
                        context?.run {
                            when (it.first) {
                                -10086 -> {
                                    if (pptErrorDialog == null) {
                                        pptErrorDialog = PPTErrorDialog.Builder(this)
                                            .setDescriptionText(it.second ?: "")
                                            .setSuggestionText(resources.getString(R.string.anim_ppt_error_suggestion_over_time))
                                            .setNegative(resources.getString(R.string.anim_ppt_error_skip_anim)) { _, _ ->
                                                pptView?.isAnimPPTEnable = false
                                            }
                                            .setPositive(resources.getString(R.string.anim_ppt_error_reload)) { _, _ -> pptView?.reloadAnimPPT() }
                                            .create()
                                    }
                                    pptErrorDialog!!.show()
                                }
                                LPConstants.ON_PPT_LOAD_FINISH_CODE -> {
                                    if (pptErrorDialog != null && pptErrorDialog!!.isShowing) {
                                        pptErrorDialog!!.dismiss()
                                    }
                                }
                            }
                        }
                    } catch (ignore: Exception) {
                        // do nothing
                    }
                }
            })
            actionShowBleDialog.observe(this@PPTFragment, Observer {
                it?.run {
                    writingboardWrapper?.showBleDialogWithPermission()
                }
            })
            closeDrawingMode.observe(this@PPTFragment, Observer {
                resetToolbar()
                laserShapeLayer.enableDrawLaser(false)
            })
            remarkEnable.observe(this@PPTFragment, Observer {
                pptView?.setRemarksEnable(it ?: false)
            })
            if (enableQaBtn()) {
                hasNewQa.observe(this@PPTFragment, Observer {
                    pptMenuLayout.tvQaTip.visibility =
                        if (it == true && !isQaOpen) View.VISIBLE else View.GONE
                })
            }
            showRollCall.observeForever(showRollCallObserver)
            dismissRollCall.observeForever(dismissRollCallObserver)
        }
    }

    private val showRollCallObserver by lazy {
        Observer<Pair<Int, OnPhoneRollCallListener.RollCall?>> {
            it?.let {
                if (it.first != -1 && routerViewModel.liveRoom.isTeacherOrAssistant) {
                    pptMenuLayout.view_roll_call_going.visibility = View.VISIBLE
                    //点名
                    toolboxWindow.setDotsVisibility(
                        getString(R.string.base_toolbox_roll_call),
                        true
                    )
                }
            }
        }
    }

    private val dismissRollCallObserver by lazy {
        Observer<Boolean> {
            if (it == false) {
                if (routerViewModel.liveRoom.isTeacherOrAssistant) {
                    pptMenuLayout.view_roll_call_going.visibility = View.GONE
                    //点名
                    toolboxWindow.setDotsVisibility(
                        getString(R.string.base_toolbox_roll_call),
                        false
                    )
                }
            }
        }
    }

    private fun updateToolbarVisible() {
        pptMenuLayout.llPenMenu.visibility =
            if ((pptView?.switchableStatus == SwitchableStatus.MaxScreen && !isFullScreen()) || pptView?.isInFullScreen == true) View.VISIBLE else View.GONE
    }

    private fun checkSyncPPTVideo() {
        if (routerViewModel.registerSyncPPTVideo.value != true) {
            routerViewModel.registerSyncPPTVideo.value = true
        }
    }

    private fun isAutoSpeak() =
        routerViewModel.liveRoom.roomType == LPConstants.LPRoomType.Single ||
                routerViewModel.liveRoom.roomType == LPConstants.LPRoomType.SmallGroup || routerViewModel.liveRoom.roomType == LPConstants.LPRoomType.OneOnOne

    override fun showSpeakClosedByTeacher(isSmallGroup: Boolean) {
        tvSpeakApply.isChecked = false
        if (!isSmallGroup) {
            enableAllToolbarItem(false)
        }
        tvCountDown.visibility = View.INVISIBLE
        pptView?.changeTouchAble(false)
    }

    override fun showSpeakClosedByServer() {
        showToastMessage(getString(R.string.live_media_speak_closed_by_server))
        with(pptMenuLayout) {
            tvSpeakApply.isChecked = false
            enableAllToolbarItem(false)
            tvCountDown.visibility = View.INVISIBLE
            right_container.visibility = View.GONE
        }
    }

    override fun showForceSpeakDenyByServer() {
        showToastMessage(getString(R.string.live_force_speak_closed_by_server))
        with(pptMenuLayout) {
            tvSpeakApply.isChecked = false
            enableAllToolbarItem(false)
            tvCountDown.visibility = View.INVISIBLE
            right_container.visibility = View.GONE
        }
    }

    override fun showSpeakApplyCountDown(countDownTime: Int, total: Int) {
        with(pptMenuLayout) {
            tvCountDown.visibility = View.VISIBLE
            tvCountDown.setRatio(countDownTime / total.toFloat())
        }
    }

    override fun showSpeakApplyDisagreed() {
        with(pptMenuLayout) {
            tvSpeakApply.isEnabled = true
            tvSpeakApply.isChecked = false
            showToastMessage(getString(R.string.live_media_speak_apply_disagree))
            tvCountDown.visibility = View.INVISIBLE
        }
    }

    override fun showSpeakApplyCanceled() {
        tvSpeakApply.isEnabled = true
        tvSpeakApply.isChecked = false
        enableAllToolbarItem(false)
        tvCountDown.visibility = View.INVISIBLE
        pptView?.changeTouchAble(false)
    }

    override fun showTeacherMenu(isGroupAdmin: Boolean) {
        with(pptMenuLayout) {
            enableAllToolbarItem(true)
            if (routerViewModel.liveRoom.isGroupTeacherOrAssistant) {
                tvPPTFiles.visibility = View.GONE
            } else {
                tvPPTFiles.visibility = View.VISIBLE
            }
            ivPPTAuth.visibility = View.VISIBLE
            ivToolBox.visibility =
                if (!isGroupAdmin && checkToolboxCanUse()) View.VISIBLE else View.GONE
            tvSpeakApply.visibility = View.GONE
        }
    }

    override fun showStudentMenu() {
        with(pptMenuLayout) {
            enableAllToolbarItem(false)
            tvPPTFiles.visibility = View.GONE
            tvSpeakApply.visibility = View.VISIBLE
        }
    }

    override fun showForbiddenHand() {
        with(pptMenuLayout) {
            tvSpeakApply.isEnabled = false
            tvCountDown.visibility = View.INVISIBLE
        }
    }

    override fun showNotForbiddenHand() {
        with(pptMenuLayout) {
            tvSpeakApply.isChecked = false
            tvSpeakApply.isEnabled = true
        }
    }

    override fun hidePPTDrawBtn() {
        showToastMessage(getString(R.string.live_student_no_auth_drawing))
        enableAllToolbarItem(false)
    }

    override fun showPPTDrawBtn() {
        showToastMessage(getString(R.string.live_student_auth_drawing))
        enableAllToolbarItem(true)
    }

    override fun showHandUpError() {
        showToastMessage(getString(R.string.live_hand_up_error))
    }

    override fun showAssistantMenu(lpAdminAuthModel: LPAdminAuthModel?) {
        enableAllToolbarItem(lpAdminAuthModel == null || lpAdminAuthModel.painter)
    }

    override fun showHandUpForbid() {
        showToastMessage(getString(R.string.live_forbid_raise_hand))
    }

    override fun showCantDraw() {
        showToastMessage(getString(R.string.live_cant_draw))
    }

    override fun showCantDrawCauseClassNotStart() {
        showToastMessage(getString(R.string.live_cant_draw_class_not_start))
    }

    override fun showWaitingTeacherAgree() {
        showToastMessage(getString(R.string.live_waiting_speak_apply_agree))
    }

    // region 获得发言权限
    override fun showAutoSpeak(isDrawingEnable: Boolean) {
        if (isDrawingEnable) {
            enableAllToolbarItem(true)
            pptView?.changeTouchAble(true)
            pptView?.pptEditMode = LPConstants.PPTEditMode.Normal
        }
        pptMenuLayout.rlSpeakWrapper.visibility = View.GONE
        clearLastCheckDrawItem()
    }

    override fun showForceSpeak(isDrawingEnable: Boolean) {
        pptMenuLayout.tvSpeakApply.isChecked = true
        if (isDrawingEnable) {
            enableAllToolbarItem(true)
            pptView?.changeTouchAble(true)
            pptView?.pptEditMode = LPConstants.PPTEditMode.Normal
        }
        pptMenuLayout.tvCountDown.visibility = View.INVISIBLE
        clearLastCheckDrawItem()
    }

    override fun showSpeakApplyAgreed(isEnableDrawing: Boolean) {
        showToastMessage(getString(R.string.live_media_speak_apply_agree))
        tvSpeakApply.isChecked = true
        if (isEnableDrawing) {
            enableAllToolbarItem(true)
            pptView?.changeTouchAble(true)
            pptView?.pptEditMode = LPConstants.PPTEditMode.Normal
        }
        tvCountDown.visibility = View.INVISIBLE
        clearLastCheckDrawItem()
    }
    // endregion

    override fun hideUserList() {
        // do nothing
    }

    override fun hideSpeakApply() {
        // do nothing
    }

    override fun showHandUpTimeout() {
        showToastMessage(getString(R.string.live_media_speak_apply_timeout))
    }

    /**
     * 更新所有画笔可见性
     */
    private fun enableAllToolbarItem(visible: Boolean) {
        resetToolbar()
        val visibility = if (visible) View.VISIBLE else View.GONE
        pptMenuLayout.run {
            ciSelect.visibility = visibility
            ciPenContainer.visibility = visibility
            ciMarkContainer.visibility = visibility
            ciGraphContainer.visibility = visibility
            ciWordContainer.visibility = visibility
            ciLaser.visibility = visibility
            ciPenClear.visibility = visibility
        }
    }

    /**
     * 检查工具箱内是否有可用的
     */
    private fun checkToolboxCanUse(): Boolean {
        val enableArray = ToolboxWindow.getEnableArray(routerViewModel.liveRoom)
        var canUse = false
        for (enable in enableArray) {
            canUse = canUse || enable
        }
        return canUse
    }

    override fun setAudition() {
        pptMenuLayout.run {
            // 试听，隐藏所有
            enableAllToolbarItem(false)
            tvPPTFiles.visibility = View.GONE
            tvAudio.visibility = View.GONE
            tvVideo.visibility = View.GONE
        }
    }

    override fun showDrawDeny() {
        showToastMessage(getString(R.string.live_room_paint_permission_forbid))
    }

    override fun hideTimer() {
        // do nothing
    }

    override fun setPresenter(presenter: RightMenuContract.Presenter?) {
        // do nothing
    }

    override fun showVideoStatus(isOn: Boolean) {
        pptMenuLayout.tvVideo.isChecked = isOn
        if (routerViewModel.liveRoom.speakQueueVM.isReplacedUser) {
            pptMenuLayout.ivAsCameraStatus.isSelected = isOn
        } else {
            pptMenuLayout.ivAsCameraStatus.isSelected = false
        }
        showToastMessage(if (isOn) getString(R.string.live_camera_on) else getString(R.string.live_camera_off))
    }

    override fun showAudioStatus(isOn: Boolean) {
        pptMenuLayout.tvAudio.isChecked = isOn
        showToastMessage(if (isOn) getString(R.string.live_mic_on) else getString(R.string.live_mic_off))
    }

    override fun enableSpeakerMode() {
        with(pptMenuLayout) {
            if (routerViewModel.liveRoom.partnerConfig.liveHideStudentCamera != 1) {
                tvVideo.visibility = View.VISIBLE
            }
            tvAudio.visibility = View.VISIBLE
        }
    }

    override fun disableSpeakerMode() {
        with(pptMenuLayout) {
            tvVideo.visibility = View.GONE
            tvAudio.visibility = View.GONE
        }
    }

    override fun showVolume(level: LPConstants.VolumeLevel) {
        //无音频大小
    }

    override fun showAudioRoomError() {
        showToastMessage(getString(R.string.live_audio_room_error))
    }

    override fun showMessage(s: String) {
        showToastMessage(s)
    }

    /**
     * 邀请发言 同意后退出全屏
     */
    override fun showSpeakInviteDlg(invite: Int) {
        if (invite == 0) { // 取消邀请;
            if (speakInviteDlg?.isShowing == true) {
                speakInviteDlg?.dismiss()
            }
            return
        }
        if (speakInviteDlg?.isShowing == true) {
            return
        }
        context?.let {
            speakInviteDlg = ThemeMaterialDialogBuilder(it)
                .content(R.string.live_invite_speak_tip)
                .positiveText(getString(R.string.live_agree))
                .negativeText(getString(R.string.live_disagree))
                .cancelable(false)
                .onPositive { materialDialog, _ ->
                    presenter.onSpeakInvite(1)
                    materialDialog.dismiss()
                    routerViewModel.exitFullScreen()
                }
                .onNegative { dialog, _ ->
                    presenter.onSpeakInvite(0)
                    dialog.dismiss()
                }
                .build()

            if (canShowDialog()) {
                speakInviteDlg?.show()
            }
        }
    }

    override fun showForceSpeakDlg(tipRes: Int) {
        if (canShowDialog()) {
            routerViewModel.exitFullScreen()
            if (forceSpeakDlg?.isShowing == true) {
                forceSpeakDlg?.dismiss()
            }
            context?.let {
                forceSpeakDlg = ThemeMaterialDialogBuilder(it)
                    .content(tipRes)
                    .positiveText(getString(R.string.live_i_got_it))
                    .onPositive { materialDialog, _ -> materialDialog.dismiss() }
                    .canceledOnTouchOutside(true)
                    .build()
                if (canShowDialog()) {
                    forceSpeakDlg?.show()
                }
            }
        }
    }

    private fun checkClassStart(): Boolean {
        return if (!routerViewModel.liveRoom.isClassStarted) {
            showToastMessage(getString(R.string.base_class_not_start_tips))
            false
        } else {
            true
        }
    }

    private var showToastCache = false

    override fun showH5PPTAuth(auth: Boolean?) {
        if (routerViewModel.canOperateH5PPT()) {
            pptMenuLayout.ivOperatePPT.isSelected = auth ?: false
        }
        if (!isAdmin(routerViewModel.liveRoom)) {
            pptMenuLayout.ivPPTAuth.visibility = if (auth == true) View.VISIBLE else View.GONE
            if (auth != true) {
                pptMenuLayout.ivPPTAuth.isChecked = false
                pptMenuLayout.ivPPTAuth.background = null
                presenter.changeDrawingStatus(ShapeChangeData(LPConstants.PPTEditMode.Normal))
            }
            val resId =
                if (auth == true) R.string.live_h5_ppt_auth_confirm_tip else R.string.live_h5_ppt_auth_cancel_tip
            if (showToastCache) {
                showMessage(getString(resId))
            } else {
                showToastCache = true
            }
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        bonusPointPopupWindow?.dismiss()
        animatorSet.removeAllListeners()
        animatorSet.cancel()
        routerViewModel.actionNavigateToMain.removeObserver(navigateToMainObserver)
        routerViewModel.showRollCall.removeObserver(showRollCallObserver)
        routerViewModel.dismissRollCall.removeObserver(dismissRollCallObserver)
        routerViewModel.switch2FullScreen.removeObserver(switch2FullScreenObserver)
        routerViewModel.switch2MaxScreen.removeObserver(switch2MaxScreenObserver)
        pptView?.destroy()
        writingboardWrapper?.onDestroy()
        presenter.unSubscribe()
        if (routerViewModel.isLiveRoomInitialized()) {
            laserShapeLayer.onDestroy()
        }
        pptContainer.removeAllViews()
        menuContainer.removeAllViews()
        LPRxUtils.dispose(disposeOfClickable)
        LPRxUtils.dispose(disposableOfBonusPointsTimer)
        if (speakInviteDlg?.isShowing == true) {
            speakInviteDlg?.dismiss()
        }
        if (forceSpeakDlg?.isShowing == true) {
            forceSpeakDlg?.dismiss()
        }
    }

    companion object {
        fun newInstance() = PPTFragment()
    }

    override fun getLayoutId(): Int = R.layout.fragment_pad_ppt

    /**
     * 更新音视频按钮可见性
     */
    private fun updateAVButtonVisibility() {
        if (enableWarmingupVideo() || isFullScreen() || routerViewModel.liveRoom.isMockLive || routerViewModel.liveRoom.isPushLive) {
            pptMenuLayout.media_container.visibility = View.GONE
        } else {
            pptMenuLayout.media_container.visibility = View.VISIBLE
        }
    }

    private val scanDeviceCallback by lazy {
        object : XYScanDeviceCallback {
            override fun onStartScan() {
                //开始搜索即进入连接状态
                writingboard_ble_progress.visibility = View.VISIBLE
                writingboard_ble_progress.setLooping(true)
            }

            override fun onScanDevice(bleDevice: BleDevice?) {
                LPLogger.d(
                    "zxyb-ble",
                    "onScanDevice name=${bleDevice?.name}, address=${bleDevice?.address}"
                )
            }

            override fun onStopScan() {
                writingboard_ble_progress.visibility = View.GONE
                writingboard_ble_progress.setLooping(false)
            }

        }
    }

    private fun initZXYBSDK() {
        writingboardWrapper = WritingboardWrapper(
            (context as AppCompatActivity?)!!,
            routerViewModel.liveRoom,
            writingboard_ble_icon
        )
        val config = WritingboardWrapper.Config()
        config.bleConnectResId = R.drawable.live_ic_writingboard_connected
        config.bleDisconnectResId = R.drawable.live_ic_writingboard_disconnected
        config.bleSleepResId = R.drawable.live_ic_writingboard_sleep
        config.usbConnectResId = R.drawable.live_ic_writingboard_usb_connected
        config.usbDisconnectResId = R.drawable.live_ic_writingboard_usb_disconnected
        config.usbSleepResId = R.drawable.live_ic_writingboard_usb_sleep
        writingboardWrapper!!.run {
            this.config = config
            deviceScanCallback = object : DeviceScanCallback {
                override fun onStartScan() {
                    writingboard_ble_progress.visibility = View.VISIBLE
                    writingboard_ble_progress.setLooping(true)
                }

                override fun onScanDevice(bleDevice: BleDevice?) {
                    // do nothing
                }

                override fun onStopScan() {
                    writingboard_ble_progress.visibility = View.GONE
                    writingboard_ble_progress.setLooping(false)
                }
            }
            connectStateCallback = object : ConnectStateCallback {
                override fun onConnectState(connectState: ZXYBConnectStatus) {
                    if (connectState == ZXYBConnectStatus.CONNECT_STATUS_SUCCESS) {
                        writingboard_ble_container.visibility = View.VISIBLE
                    }
                    if (connectState == ZXYBConnectStatus.CONNECT_STATUS_CONNECTING) {
                        writingboard_ble_progress.visibility = View.VISIBLE
                        writingboard_ble_progress.setLooping(true)
                    } else {
                        writingboard_ble_progress.visibility = View.GONE
                        writingboard_ble_progress.setLooping(false)
                    }
                }
            }
        }
        routerViewModel.liveRoom.zxybvm.run {
            compositeDisposable.addAll(observableOfXYDataPacket.observeOn(AndroidSchedulers.mainThread())
                .filter { enableDrawingAuth() }
                .subscribe {
                    val info = LaserShapeLayer.PositionInfo()
                    pptView?.getPPTPagePositionInfo(info)
                    connectedDevice?.run {
                        val ratio = if (1.0f * maxX / maxY > 1.0f * info.width / info.height) {
                            //高度占满
                            1.0f * info.height / maxY
                        } else {
                            1.0f * info.width / maxX
                        }
                        it.tx = it.x * ratio + info.offsetWidth
                        it.ty = it.y * ratio + info.offsetHeight
                        motionEvent.setXyDataPacket(it)
                        if (laserShapeLayer.isEnableDrawLaser) {
                            laserShapeLayer.onTouchEvent(motionEvent)
                        } else {
                            pptView?.onZXYBMotionEvent(motionEvent)
                        }
                    }
                },
                observableOfSoftKey.observeOn(AndroidSchedulers.mainThread())
                    .subscribe {
                        doSoftKeyCallBack(it)
                    })
        }
    }

    private var shapeStrokeWidthIndex = 0
    private var shapeColorIndex = 0
    private val graphStrokeWidthArray = arrayOf(0, 2, 4, 6)

    private fun doSoftKeyCallBack(keyCode: Int) {
        pptView?.run {
            when (keyCode) {
                101 -> {
                    //鼠标
                }
                102 -> {
                    //上一页
                    if (enableSwitchPPT()) {
                        gotoPrevPage()
                    }
                }
                103 -> {
                    //下一页
                    if (enableSwitchPPT()) {
                        if (currentPageIndex < maxPage || isAdmin(routerViewModel.liveRoom)) {
                            gotoNextPage()
                        }
                    }
                }
                104 -> {
                    //选择
                    if (!pptMenuLayout.ciSelect.isChecked && enableDrawingAuth()) {
                        presenter.changeDrawing(ShapeChangeData(LPConstants.PPTEditMode.SelectMode))
                        if (presenter.canStudentDraw()) {
                            updateToolbarItemCheck(pptMenuLayout.ciSelect, true)
                            laserShapeLayer.enableDrawLaser(false)
                        }
                    }
                }
                105 -> {
                    //画笔
                    if (!pptMenuLayout.ciPen.isChecked && enableDrawingAuth()) {
                        presenter.changeDrawing(
                            ShapeChangeData(
                                SelectSrc.Brush,
                                LPConstants.PPTEditMode.ShapeMode,
                                LPConstants.ShapeType.Doodle
                            )
                        )
                        if (presenter.canStudentDraw()) {
                            updateToolbarItemCheck(pptMenuLayout.ciPen, true)
                            laserShapeLayer.enableDrawLaser(false)
                        }
                    }
                }
                106 -> {
                    //马克笔
                    if (!pptMenuLayout.ciMark.isChecked && enableDrawingAuth()) {
                        presenter.changeDrawing(
                            ShapeChangeData(
                                SelectSrc.Marker,
                                LPConstants.PPTEditMode.ShapeMode,
                                LPConstants.ShapeType.MarkerDoodle
                            )
                        )
                        if (presenter.canStudentDraw()) {
                            updateToolbarItemCheck(pptMenuLayout.ciMark, true)
                            laserShapeLayer.enableDrawLaser(false)
                        }
                    }
                }
                107 -> {
                    //箭头
                    if (!pptMenuLayout.ciGraph.isChecked && enableDrawingAuth()) {
                        presenter.changeDrawing(
                            ShapeChangeData(
                                SelectSrc.Graph,
                                LPConstants.PPTEditMode.ShapeMode,
                                LPConstants.ShapeType.Arrow
                            )
                        )
                        if (presenter.canStudentDraw()) {
                            updateToolbarItemCheck(pptMenuLayout.ciGraph, true)
                            laserShapeLayer.enableDrawLaser(false)
                        }
                        graphPopupWindow.checkedIndex(1)
                        routerViewModel.drawGraphChange.value = graphPopupWindow.OnShapeChangeModel(
                            LPConstants.ShapeType.Arrow,
                            R.drawable.base_ic_graph_arrow_unpress,
                            R.drawable.base_ic_graph_arrow_press
                        )
                    }
                }
                108 -> {
                    //橡皮
                    if (isEraseMode && enableDrawingAuth()) {
                        if (!pptMenuLayout.ciPenClear.isChecked) {
                            presenter.changeDrawing(ShapeChangeData(LPConstants.PPTEditMode.EraserMode))
                            if (presenter.canStudentDraw()) {
                                updateToolbarItemCheck(pptMenuLayout.ciPenClear, true)
                                laserShapeLayer.enableDrawLaser(false)
                            }
                        }
                    } else {
                        pptView?.run {
                            eraseShapes()
                        }
                    }
                    updateEraserMode(true)
                }
                109 -> {
                    //颜色,更新所有颜色
                    //画笔和马克笔上面有4种线宽，图像则有9个图像+4个线宽
                    if (pptEditMode != LPConstants.PPTEditMode.ShapeMode) {
                        return
                    }
                    brushPopupWindow.checkedColorIndex(shapeColorIndex + 4)
                    markerPopupWindow.checkedColorIndex(shapeColorIndex + 4)
                    graphPopupWindow.checkedColorIndex(shapeColorIndex + 9 + 4)
                    wordPopupWindow.checkedColorIndex(shapeColorIndex)
                    shapeColorIndex =
                        (shapeColorIndex + 1) % BaseAutoArrangePopupWindow.colorIds.size
                }
                110 -> {
                    //线宽,所有线宽均更新
                    //直接% 4,线宽数量是一致的
                    if (pptEditMode != LPConstants.PPTEditMode.ShapeMode) {
                        return
                    }
                    val brushStrokeWidth =
                        BaseDrawWidthSettingWindow.pencilPaintSize[shapeStrokeWidthIndex].toFloat()
                    val markerStrokeWidth =
                        BaseDrawWidthSettingWindow.markerPaintSize[shapeStrokeWidthIndex].toFloat()
                    val graphStrokeWidth =
                        graphStrokeWidthArray[shapeStrokeWidthIndex].toFloat()
                    widthSelectCache[SelectSrc.Brush] = brushStrokeWidth
                    widthSelectCache[SelectSrc.Marker] = markerStrokeWidth
                    brushPopupWindow.checkedIndex(shapeStrokeWidthIndex)
                    markerPopupWindow.checkedIndex(shapeStrokeWidthIndex)
                    graphPopupWindow.checkedIndex(shapeStrokeWidthIndex + 9)
                    if (pptShapeType == LPConstants.ShapeType.Doodle) {
                        setShapeStrokeWidth(brushStrokeWidth)
                    } else if (pptShapeType == LPConstants.ShapeType.MarkerDoodle) {
                        setShapeStrokeWidth(markerStrokeWidth)
                    }
                    setCustomShapeStrokeWidth(graphStrokeWidth)
                    shapeStrokeWidthIndex = (shapeStrokeWidthIndex + 1) % 4
                }
                111 -> {
                    //f1
                }
                112 -> {
                    //f2
                }
            }
        }
    }
}